package com.justnow.offer;

import java.util.LinkedList;
import java.util.Random;

/**
 * @author justnow
 * Created on 2020-09-30
 * Description
 * 滑动时间窗口限流实现
 * 假设某个服务最多只能每秒钟处理100个请求，我们可以设置一个1秒钟的滑动时间窗口，
 * 窗口中有10个格子，每个格子100毫秒，每100毫秒移动一次，每次移动都需要记录当前服务请求的次数
 */
public class SlidingTimeWindow {

    public final int limit = 100;
    //服务访问次数
    Long counter = 0L;

    LinkedList<Long> slots = new LinkedList<>();

    int split = 10;

    boolean isLimit = false;

    private void doCheck() throws InterruptedException {
        while (true) {
            slots.addLast(counter);
            if (slots.size() > split) {
                slots.removeFirst(); // 超出了，就把第一个移除；
            }
            if ((slots.peekLast() - slots.peekFirst()) > limit) {
                System.out.println("限流了。。");
                isLimit = true;
            } else {
                isLimit = false;
            }
            Thread.sleep(1000/split);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SlidingTimeWindow timeWindow = new SlidingTimeWindow();
        new Thread(() -> {
            try {
                timeWindow.doCheck();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        while (true) {
            if (!timeWindow.isLimit) {
                timeWindow.counter++;
                Thread.sleep(new Random().nextInt(15));
                System.out.println("业务方法被执行完了。。。");
            }  else {
                System.out.println("被限流了，直接返回给用户");
            }
        }

    }


}
